Test program to make sure GtkTextBuffer is in working order.
authorHavoc Pennington <hp@pobox.com>
Fri, 2 Jun 2000 17:27:21 +0000 (17:27 +0000)
committerHavoc Pennington <hp@src.gnome.org>
Fri, 2 Jun 2000 17:27:21 +0000 (17:27 +0000)
2000-06-02  Havoc Pennington  <hp@pobox.com>

        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
is in working order.

* gtk/testtext.c: Change to reflect anonymous mark API

* gtk/gtktextview.c: Convert from mark names to GtkTextMark*.

* gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
field, which was unused.

* gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
saves some typing.

* gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*

* gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
flag on the insertion point and selection bound

Throughout, use GtkTextMark instead of GtkTextLineSegment, and
make mark-manipulation functions take a GtkTextMark* instead of a
mark name.

* gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to
GtkTextMarkBody; will be used to detect attempts to delete
the permanent marks (insert and selection bound)

23 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
gtk/Makefile.am
gtk/gtktextbtree.c
gtk/gtktextbtree.h
gtk/gtktextbuffer.c
gtk/gtktextbuffer.h
gtk/gtktextiter.c
gtk/gtktextlayout.c
gtk/gtktextmark.c
gtk/gtktextmarkprivate.h
gtk/gtktexttag.h
gtk/gtktextview.c
gtk/gtktextview.h
gtk/testtext.c
gtk/testtextbuffer.c [new file with mode: 0644]
tests/testtext.c
tests/testtextbuffer.c [new file with mode: 0644]

index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index d33cfd8bca0597ecbf5839e51c62cc6b307ca053..4fd0965fc7252bef4b2b8c55781b46efe8566f8a 100644 (file)
@@ -1,3 +1,33 @@
+2000-06-02  Havoc Pennington  <hp@pobox.com>
+
+        * gtk/testtextbuffer.c: Test program to make sure GtkTextBuffer
+       is in working order.
+       
+       * gtk/testtext.c: Change to reflect anonymous mark API
+
+       * gtk/gtktextview.c: Convert from mark names to GtkTextMark*.
+
+       * gtk/gtktexttag.h (struct _GtkTextTag): remove the affects_size
+       field, which was unused.
+
+       * gtk/gtktextmarkprivate.h (GTK_IS_TEXT_MARK): add this macro,
+       saves some typing.
+
+       * gtk/gtktextbuffer.c: Switch from mark names to GtkTextMark*   
+
+       * gtk/gtktextbtree.c (gtk_text_btree_new): set the not_deleteable
+       flag on the insertion point and selection bound
+
+       Throughout, use GtkTextMark instead of GtkTextLineSegment, and 
+       make mark-manipulation functions take a GtkTextMark* instead of a
+       mark name.
+       
+       * gtk/gtktextmarkprivate.h: Add a "not_deleteable" flag to 
+       GtkTextMarkBody; will be used to detect attempts to delete
+       the permanent marks (insert and selection bound)
+
+       * gtk/Makefile.am (noinst_PROGRAMS): add testtextbuffer 
+
 Fri Jun  2 12:56:01 2000  Owen Taylor  <otaylor@redhat.com>
 
        * gtk/gtkwidget.c (gtk_widget_init): Initialize DOUBLE_BUFFERED
index c1c40aabd5caf47b375d437d70fba9b71d71ae6f..d265d1d0b04cbcbb3ff38100b586146da72a4dcf 100644 (file)
@@ -487,7 +487,7 @@ uninstall-local:
 #
 # test programs, not to be installed
 #
-noinst_PROGRAMS = testgtk testcalendar testinput testselection testrgb testdnd testtext simple # testthreads
+noinst_PROGRAMS = testgtk testcalendar testinput testselection testrgb testdnd testtext simple testtextbuffer # testthreads
 DEPS = libgtk.la $(top_builddir)/gdk/libgdk.la
 LDADDS = @STRIP_BEGIN@ \
        libgtk.la                       \
@@ -514,6 +514,7 @@ testgtk_LDADD = $(LDADDS)
 testinput_LDADD = $(LDADDS)
 testselection_LDADD = $(LDADDS)
 testtext_LDADD = $(LDADDS)
+testtextbuffer_LDADD = $(LDADDS)
 testrgb_LDADD = $(LDADDS)
 testdnd_LDADD = $(LDADDS)
 simple_LDADD = $(LDADDS)
index 412a41c3c4e2b52f7b8cc108a1213a252ab06558..ebbe0d92e81d3ddc3a6a593d5e1437f74fd196fd 100644 (file)
@@ -63,6 +63,7 @@
 #include "gtktextlayout.h"
 #include "gtktextiterprivate.h"
 #include "gtkdebug.h"
+#include "gtktextmarkprivate.h"
 
 /*
  * Types
@@ -417,19 +418,27 @@ gtk_text_btree_new (GtkTextTagTable *table,
     gtk_text_btree_get_iter_at_line_char(tree, &start, 0, 0);
     
 
-    tree->insert_mark = gtk_text_btree_set_mark(tree,
-                                                "insert",
-                                                FALSE,
-                                                &start,
-                                                FALSE);
-
+    tree->insert_mark =
+      (GtkTextLineSegment*) gtk_text_btree_set_mark(tree,
+                                                    NULL,
+                                                    "insert",
+                                                    FALSE,
+                                                    &start,
+                                                    FALSE);
+    
+    tree->insert_mark->body.mark.not_deleteable = TRUE;
+    
     tree->insert_mark->body.mark.visible = TRUE;
     
-    tree->selection_bound_mark = gtk_text_btree_set_mark(tree,
-                                                         "selection_bound",
-                                                         FALSE,
-                                                         &start,
-                                                         FALSE);
+    tree->selection_bound_mark =
+      (GtkTextLineSegment*) gtk_text_btree_set_mark(tree,
+                                                    NULL,
+                                                    "selection_bound",
+                                                    FALSE,
+                                                    &start,
+                                                    FALSE);
+
+    tree->selection_bound_mark->body.mark.not_deleteable = TRUE;
     
     mark_segment_ref(tree->insert_mark);
     mark_segment_ref(tree->selection_bound_mark);
@@ -2310,7 +2319,7 @@ redisplay_mark(GtkTextLineSegment *mark)
     
   gtk_text_btree_get_iter_at_mark(mark->body.mark.tree,
                                   &iter,
-                                  mark);
+                                  (GtkTextMark*)mark);
 
   end = iter;
   gtk_text_iter_forward_char(&end);
@@ -2340,6 +2349,7 @@ ensure_not_off_end(GtkTextBTree *tree,
 
 static GtkTextLineSegment*
 real_set_mark(GtkTextBTree *tree,
+              GtkTextMark *existing_mark,
               const gchar *name,
               gboolean left_gravity,
               const GtkTextIter *where,
@@ -2350,13 +2360,17 @@ real_set_mark(GtkTextBTree *tree,
   GtkTextIter iter;
   
   g_return_val_if_fail(tree != NULL, NULL);
-  g_return_val_if_fail(name != NULL, NULL);
   g_return_val_if_fail(where != NULL, NULL);
   g_return_val_if_fail(gtk_text_iter_get_btree(where) == tree, NULL);
-  
-  mark = g_hash_table_lookup(tree->mark_table,
-                             name);
 
+  if (existing_mark)
+    mark = (GtkTextLineSegment*) existing_mark;
+  else if (name != NULL)
+    mark = g_hash_table_lookup(tree->mark_table,
+                               name);
+  else
+    mark = NULL;
+  
   if (should_exist && mark == NULL)
     {
       g_warning("No mark `%s' exists!", name);
@@ -2376,7 +2390,7 @@ real_set_mark(GtkTextBTree *tree,
        {
          GtkTextIter old_pos;
 
-         gtk_text_btree_get_iter_at_mark (tree, &old_pos, mark);
+         gtk_text_btree_get_iter_at_mark (tree, &old_pos, (GtkTextMark*)mark);
          redisplay_region (tree, &old_pos, where);
        }
       
@@ -2411,9 +2425,10 @@ real_set_mark(GtkTextBTree *tree,
 
       mark->body.mark.line = gtk_text_iter_get_line(&iter);
 
-      g_hash_table_insert(tree->mark_table,
-                          mark->body.mark.name,
-                          mark);
+      if (mark->body.mark.name)
+        g_hash_table_insert(tree->mark_table,
+                            mark->body.mark.name,
+                            mark);
     }
   
   /* Link mark into new location */
@@ -2432,15 +2447,17 @@ real_set_mark(GtkTextBTree *tree,
 }
 
 
-GtkTextLineSegment*
+GtkTextMark*
 gtk_text_btree_set_mark (GtkTextBTree *tree,
+                         GtkTextMark  *existing_mark,
                          const gchar *name,
                          gboolean left_gravity,
                          const GtkTextIter *iter,
                          gboolean should_exist)
 {
-  return real_set_mark(tree, name, left_gravity, iter, should_exist,
-                       TRUE);  
+  return (GtkTextMark*)real_set_mark(tree, existing_mark,
+                                     name, left_gravity, iter, should_exist,
+                                     TRUE);  
 }
 
 gboolean
@@ -2448,8 +2465,10 @@ gtk_text_btree_get_selection_bounds (GtkTextBTree *tree,
                                     GtkTextIter  *start,
                                     GtkTextIter  *end)
 {
-  gtk_text_btree_get_iter_at_mark (tree, start, tree->insert_mark);
-  gtk_text_btree_get_iter_at_mark (tree, end, tree->selection_bound_mark);
+  gtk_text_btree_get_iter_at_mark (tree, start,
+                                   (GtkTextMark*)tree->insert_mark);
+  gtk_text_btree_get_iter_at_mark (tree, end,
+                                   (GtkTextMark*)tree->selection_bound_mark);
   
   if (gtk_text_iter_equal(start, end))
     return FALSE;
@@ -2470,15 +2489,17 @@ gtk_text_btree_place_cursor(GtkTextBTree *tree,
     redisplay_region(tree, &start, &end);
   
   /* Move insert AND selection_bound before we redisplay */
-  real_set_mark(tree, "insert", FALSE, iter, TRUE, FALSE);
-  real_set_mark(tree, "selection_bound", FALSE, iter, TRUE, FALSE);
+  real_set_mark(tree, (GtkTextMark*) tree->insert_mark,
+                "insert", FALSE, iter, TRUE, FALSE);
+  real_set_mark(tree, (GtkTextMark*) tree->selection_bound_mark,
+                "selection_bound", FALSE, iter, TRUE, FALSE);
 }
 
 void
 gtk_text_btree_remove_mark_by_name (GtkTextBTree *tree,
                                     const gchar *name)
 {
-  GtkTextLineSegment *mark;
+  GtkTextMark *mark;
 
   g_return_if_fail(tree != NULL);
   g_return_if_fail(name != NULL);
@@ -2491,35 +2512,44 @@ gtk_text_btree_remove_mark_by_name (GtkTextBTree *tree,
 
 void
 gtk_text_btree_remove_mark (GtkTextBTree *tree,
-                            GtkTextLineSegment *segment)
+                            GtkTextMark *mark)
 {
+  GtkTextLineSegment *segment = (GtkTextLineSegment*) mark;
+  
   g_return_if_fail(segment != NULL);
   g_return_if_fail(segment != tree->selection_bound_mark);
   g_return_if_fail(segment != tree->insert_mark);
   g_return_if_fail(tree != NULL);
+
+  if (segment->body.mark.not_deleteable)
+    {
+      g_warning("Can't delete special mark `%s'", segment->body.mark.name);
+      return;
+    }
   
   gtk_text_btree_unlink_segment(tree, segment, segment->body.mark.line);
   /* FIXME should probably cleanup_line but Tk didn't */
-  g_hash_table_remove(tree->mark_table, segment->body.mark.name);
+  if (segment->body.mark.name)
+    g_hash_table_remove(tree->mark_table, segment->body.mark.name);
   mark_segment_unref(segment);
   segments_changed(tree);
 }
 
 gboolean
 gtk_text_btree_mark_is_insert (GtkTextBTree *tree,
-                               GtkTextLineSegment *segment)
+                               GtkTextMark *segment)
 {
-  return segment == tree->insert_mark;
+  return segment == (GtkTextMark*) tree->insert_mark;
 }
 
 gboolean
 gtk_text_btree_mark_is_selection_bound (GtkTextBTree *tree,
-                                        GtkTextLineSegment *segment)
+                                        GtkTextMark *segment)
 {
-  return segment == tree->selection_bound_mark;
+  return segment == (GtkTextMark*) tree->selection_bound_mark;
 }
 
-GtkTextLineSegment*
+GtkTextMark*
 gtk_text_btree_get_mark_by_name (GtkTextBTree *tree,
                                  const gchar *name)
 {
index 91b37af7591aaf72724af36d5278cea7c7897390..0c594c3c85a404de5b1c580c9f711ab1fbe8fa82 100644 (file)
@@ -117,7 +117,7 @@ gboolean gtk_text_btree_get_iter_at_mark_name    (GtkTextBTree       *tree,
                                                   const gchar        *mark_name);
 void     gtk_text_btree_get_iter_at_mark         (GtkTextBTree       *tree,
                                                   GtkTextIter        *iter,
-                                                  GtkTextLineSegment *mark);
+                                                  GtkTextMark        *mark);
 void     gtk_text_btree_get_last_iter            (GtkTextBTree       *tree,
                                                   GtkTextIter        *iter);
 void     gtk_text_btree_get_iter_at_line         (GtkTextBTree       *tree,
@@ -133,25 +133,26 @@ gboolean gtk_text_btree_get_iter_at_last_toggle  (GtkTextBTree       *tree,
 
 
 /* Manipulate marks */
-GtkTextLineSegment *gtk_text_btree_set_mark                (GtkTextBTree       *tree,
+GtkTextMark        *gtk_text_btree_set_mark                (GtkTextBTree       *tree,
+                                                            GtkTextMark         *existing_mark,
                                                            const gchar        *name,
                                                            gboolean            left_gravity,
                                                            const GtkTextIter  *index,
-                                                           gboolean            should_exist);
+                                                            gboolean           should_exist);
 void                gtk_text_btree_remove_mark_by_name     (GtkTextBTree       *tree,
                                                            const gchar        *name);
 void                gtk_text_btree_remove_mark             (GtkTextBTree       *tree,
-                                                           GtkTextLineSegment *segment);
+                                                           GtkTextMark        *segment);
 gboolean            gtk_text_btree_get_selection_bounds    (GtkTextBTree       *tree,
                                                            GtkTextIter        *start,
                                                            GtkTextIter        *end);
 void                gtk_text_btree_place_cursor            (GtkTextBTree       *tree,
                                                            const GtkTextIter  *where);
 gboolean            gtk_text_btree_mark_is_insert          (GtkTextBTree       *tree,
-                                                           GtkTextLineSegment *segment);
+                                                           GtkTextMark        *segment);
 gboolean            gtk_text_btree_mark_is_selection_bound (GtkTextBTree       *tree,
-                                                           GtkTextLineSegment *segment);
-GtkTextLineSegment *gtk_text_btree_get_mark_by_name        (GtkTextBTree       *tree,
+                                                           GtkTextMark        *segment);
+GtkTextMark        *gtk_text_btree_get_mark_by_name        (GtkTextBTree       *tree,
                                                            const gchar        *name);
 GtkTextLine *       gtk_text_btree_first_could_contain_tag (GtkTextBTree       *tree,
                                                            GtkTextTag         *tag);
index 8fe51fb13f0d78f1f3f7a18c8a4a9da4dc094fc2..75af349bf31053911913bf2f130c67abfacb32f1 100644 (file)
@@ -377,7 +377,9 @@ gtk_text_buffer_insert_at_cursor (GtkTextBuffer *buffer,
   g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
   g_return_if_fail(text != NULL);
 
-  gtk_text_buffer_get_iter_at_mark(buffer, &iter, "insert");
+  gtk_text_buffer_get_iter_at_mark(buffer, &iter,
+                                   gtk_text_buffer_get_mark (buffer,
+                                                             "insert"));
 
   gtk_text_buffer_insert(buffer, &iter, text, len);
 }
@@ -700,7 +702,7 @@ gtk_text_buffer_insert_pixmap_at_char (GtkTextBuffer      *buffer,
 static void
 gtk_text_buffer_mark_set (GtkTextBuffer     *buffer,
                          const GtkTextIter *location,
-                         const char        *mark_name)
+                          GtkTextMark       *mark)
 {
   /* IMO this should NOT work like insert_text and delete_text,
      where the real action happens in the default handler.
@@ -714,7 +716,7 @@ gtk_text_buffer_mark_set (GtkTextBuffer     *buffer,
   gtk_signal_emit(GTK_OBJECT(buffer),
                   signals[MARK_SET],
                   &location,
-                  mark_name);
+                  mark);
 
 }
 
@@ -734,17 +736,19 @@ gtk_text_buffer_mark_set (GtkTextBuffer     *buffer,
  **/
 static GtkTextMark*
 gtk_text_buffer_set_mark(GtkTextBuffer *buffer,
+                         GtkTextMark *existing_mark,
                          const gchar *mark_name,
                          const GtkTextIter *iter,
                          gboolean left_gravity,
                          gboolean should_exist)
 {
   GtkTextIter location;
-  GtkTextLineSegment *mark;
+  GtkTextMark *mark;
   
   g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL);
   
   mark = gtk_text_btree_set_mark(buffer->tree,
+                                 existing_mark,
                                  mark_name,
                                  left_gravity,
                                  iter,
@@ -759,8 +763,8 @@ gtk_text_buffer_set_mark(GtkTextBuffer *buffer,
   gtk_text_btree_get_iter_at_mark(buffer->tree,
                                   &location,
                                   mark);
-
-  gtk_text_buffer_mark_set (buffer, &location, mark_name);
+  
+  gtk_text_buffer_mark_set (buffer, &location, mark);
 
   return (GtkTextMark*)mark;
 }
@@ -771,64 +775,59 @@ gtk_text_buffer_create_mark(GtkTextBuffer *buffer,
                             const GtkTextIter *where,
                             gboolean left_gravity)
 {
-  return gtk_text_buffer_set_mark(buffer, mark_name, where,
+  return gtk_text_buffer_set_mark(buffer, NULL, mark_name, where,
                                   left_gravity, FALSE);
 }
 
 void
 gtk_text_buffer_move_mark(GtkTextBuffer *buffer,
-                          const gchar *mark_name,
+                          GtkTextMark *mark,
                           const GtkTextIter *where)
 {
-  gtk_text_buffer_set_mark(buffer, mark_name, where, FALSE, TRUE);
+  g_return_if_fail (mark != NULL);
+  
+  gtk_text_buffer_set_mark(buffer, mark, NULL, where, FALSE, TRUE);
 }
 
-gboolean
+void
 gtk_text_buffer_get_iter_at_mark(GtkTextBuffer *buffer,
                                  GtkTextIter *iter,
-                                 const gchar *name)
+                                 GtkTextMark *mark)
 {
-  g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), FALSE);
+  g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
 
-  return gtk_text_btree_get_iter_at_mark_name(buffer->tree,
-                                              iter,
-                                              name);
+  gtk_text_btree_get_iter_at_mark(buffer->tree,
+                                  iter,
+                                  mark);
 }
 
 void
 gtk_text_buffer_delete_mark(GtkTextBuffer *buffer,
-                            const gchar *name)
+                            GtkTextMark *mark)
 {
   g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
 
-  if (strcmp(name, "insert") == 0 ||
-      strcmp(name, "selection_bound") == 0)
-    {
-      g_warning("Can't delete special mark `%s'", name);
-      return;
-    }
-
-  gtk_text_btree_remove_mark_by_name(buffer->tree, name);
+  gtk_text_btree_remove_mark (buffer->tree, mark);
 
   /* See rationale above for MARK_SET on why we emit this after
      removing the mark, rather than removing the mark in a default
      handler. */
   gtk_signal_emit(GTK_OBJECT(buffer), signals[MARK_DELETED],
-                  name);
+                  mark);
 }
 
 GtkTextMark*
 gtk_text_buffer_get_mark (GtkTextBuffer      *buffer,
                           const gchar         *name)
 {
-  GtkTextLineSegment *seg;
+  GtkTextMark *mark;
 
   g_return_val_if_fail(GTK_IS_TEXT_BUFFER(buffer), NULL);
   g_return_val_if_fail(name != NULL, NULL);
   
-  seg = gtk_text_btree_get_mark_by_name(buffer->tree, name);
+  mark = gtk_text_btree_get_mark_by_name(buffer->tree, name);
 
-  return (GtkTextMark*)seg;
+  return mark;
 }
 
 void
@@ -838,8 +837,12 @@ gtk_text_buffer_place_cursor (GtkTextBuffer     *buffer,
   g_return_if_fail(GTK_IS_TEXT_BUFFER(buffer));
   
   gtk_text_btree_place_cursor(buffer->tree, where);
-  gtk_text_buffer_mark_set (buffer, where, "insert");
-  gtk_text_buffer_mark_set (buffer, where, "selection_bound");
+  gtk_text_buffer_mark_set (buffer, where,
+                            gtk_text_buffer_get_mark (buffer,
+                                                      "insert"));
+  gtk_text_buffer_mark_set (buffer, where,
+                            gtk_text_buffer_get_mark (buffer,
+                                                      "selection_bound"));
 }
 
 /*
@@ -1233,11 +1236,15 @@ selection_clear_event(GtkWidget *widget, GdkEventSelection *event,
       GtkTextIter insert;
       GtkTextIter selection_bound;
 
-      gtk_text_buffer_get_iter_at_mark(buffer, &insert, "insert");
-      gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound, "selection_bound");
+      gtk_text_buffer_get_iter_at_mark(buffer, &insert,
+                                       gtk_text_buffer_get_mark (buffer, "insert"));
+      gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound,
+                                       gtk_text_buffer_get_mark (buffer, "selection_bound"));
       
       if (!gtk_text_iter_equal(&insert, &selection_bound))
-        gtk_text_buffer_move_mark(buffer, "selection_bound", &insert);
+        gtk_text_buffer_move_mark(buffer,
+                                  gtk_text_buffer_get_mark (buffer, "selection_bound"),
+                                  &insert);
     }
   else if (event->selection == clipboard_atom)
     {
@@ -1347,6 +1354,7 @@ selection_received (GtkWidget        *widget,
   GtkTextBuffer *buffer;
   gboolean reselect;
   GtkTextIter insert_point;
+  GtkTextMark *paste_point_override;
   enum {INVALID, STRING, CTEXT, UTF8} type;
 
   g_return_if_fail (widget != NULL);
@@ -1373,15 +1381,22 @@ selection_received (GtkWidget        *widget,
       return;
     }
 
-  if (gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
-                                       "__paste_point_override"))
+  paste_point_override = gtk_text_buffer_get_mark (buffer,
+                                                   "__paste_point_override");
+  
+  if (paste_point_override != NULL)
     {
-      gtk_text_buffer_delete_mark(buffer, "__paste_point_override");
+      gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
+                                       paste_point_override);
+      gtk_text_buffer_delete_mark(buffer,
+                                  gtk_text_buffer_get_mark (buffer,
+                                                            "__paste_point_override"));
     }
   else
     {
       gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
-                                       "insert");
+                                       gtk_text_buffer_get_mark (buffer,
+                                                                 "insert"));
     }
   
   reselect = FALSE;
@@ -1594,11 +1609,15 @@ cut_or_copy(GtkTextBuffer *buffer,
   if (!gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
     {
       /* Let's try the anchor thing */
-
-      if (!gtk_text_buffer_get_iter_at_mark(buffer, &end, "anchor"))
+      GtkTextMark * anchor = gtk_text_buffer_get_mark (buffer, "anchor");
+      
+      if (anchor == NULL)
         return;
       else
-        gtk_text_iter_reorder(&start, &end);
+        {
+          gtk_text_buffer_get_iter_at_mark(buffer, &end, anchor);
+          gtk_text_iter_reorder(&start, &end);
+        }
     }
 
   if (!gtk_text_iter_equal(&start, &end))
index 66f770ab14e6071b61aa54d5d727fa8c250b41b6..c57354b17bf0404eba9998015c17e8263950955a 100644 (file)
@@ -68,10 +68,10 @@ struct _GtkTextBufferClass {
   /* Mark moved or created */
   void (* mark_set)           (GtkTextBuffer *buffer,
                                const GtkTextIter *location,
-                               const gchar *mark_name);
+                               GtkTextMark *mark);
 
   void (* mark_deleted)       (GtkTextBuffer *buffer,
-                               const gchar *mark_name);
+                               GtkTextMark *mark);
 
   void (* apply_tag)          (GtkTextBuffer *buffer,
                                GtkTextTag *tag,
@@ -176,10 +176,10 @@ GtkTextMark   *gtk_text_buffer_create_mark (GtkTextBuffer     *buffer,
                                             const GtkTextIter *where,
                                             gboolean           left_gravity);
 void           gtk_text_buffer_move_mark   (GtkTextBuffer     *buffer,
-                                            const gchar       *mark_name,
+                                            GtkTextMark       *mark,
                                             const GtkTextIter *where);
 void           gtk_text_buffer_delete_mark (GtkTextBuffer     *buffer,
-                                            const gchar       *name);
+                                            GtkTextMark       *mark);
 GtkTextMark   *gtk_text_buffer_get_mark    (GtkTextBuffer     *buffer,
                                             const gchar       *name);
 
@@ -233,9 +233,9 @@ void     gtk_text_buffer_get_last_iter         (GtkTextBuffer *buffer,
 void     gtk_text_buffer_get_bounds            (GtkTextBuffer *buffer,
                                                 GtkTextIter   *start,
                                                 GtkTextIter   *end);
-gboolean gtk_text_buffer_get_iter_at_mark      (GtkTextBuffer *buffer,
+void     gtk_text_buffer_get_iter_at_mark      (GtkTextBuffer *buffer,
                                                 GtkTextIter   *iter,
-                                                const gchar   *name);
+                                                GtkTextMark   *mark);
 
 
 /* There's no get_first_iter because you just get the iter for
index 41a16916c205a37ba18fe3748abfa8dc545a43a3..8cc5f783e20a7ea7c6590015f7831eaff56ca398 100644 (file)
@@ -952,7 +952,7 @@ forward_line_leaving_caches_unmodified(GtkTextRealIter *real)
   g_assert(new_line != real->line);
   
   if (new_line != NULL)
-    {
+    {      
       real->line = new_line;
 
       real->line_byte_offset = 0;
@@ -2153,7 +2153,7 @@ gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
                                        GtkTextIter *iter,
                                        const gchar *mark_name)
 {
-  GtkTextLineSegment *mark;
+  GtkTextMark *mark;
   
   g_return_val_if_fail(iter != NULL, FALSE);
   g_return_val_if_fail(tree != NULL, FALSE);
@@ -2173,15 +2173,17 @@ gtk_text_btree_get_iter_at_mark_name (GtkTextBTree *tree,
 void
 gtk_text_btree_get_iter_at_mark (GtkTextBTree *tree,
                                   GtkTextIter *iter,
-                                  GtkTextLineSegment *mark)
+                                  GtkTextMark *mark)
 {
+  GtkTextLineSegment *seg = (GtkTextLineSegment*) mark;
+  
   g_return_if_fail(iter != NULL);
   g_return_if_fail(tree != NULL);
-  g_return_if_fail(mark->type == &gtk_text_left_mark_type ||
-                   mark->type == &gtk_text_right_mark_type);
+  g_return_if_fail(GTK_IS_TEXT_MARK (mark));
   
-  iter_init_from_segment(iter, tree, mark->body.mark.line, mark);
-  g_assert(mark->body.mark.line == gtk_text_iter_get_line(iter));
+  iter_init_from_segment(iter, tree,
+                         seg->body.mark.line, seg);
+  g_assert(seg->body.mark.line == gtk_text_iter_get_line(iter));
   check_invariants(iter);
 }
 
index 6bf09515ff30730f42456d1d69de573efc09c061..a6bb822c6ed60e773ee310423793abd7d39cdfb8 100644 (file)
@@ -757,7 +757,7 @@ gtk_text_layout_real_get_log_attrs (GtkTextLayout  *layout,
 {
   GtkTextLineDisplay *display;
   
-  g_return_val_if_fail (GTK_IS_TEXT_LAYOUT (layout), NULL);
+  g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
   
   display = gtk_text_layout_get_line_display (layout, line, TRUE);
   pango_layout_get_log_attrs (display->layout, attrs, n_attrs);
@@ -1116,7 +1116,7 @@ add_cursor (GtkTextLayout      *layout,
 
   /* Hide insertion cursor when we have a selection
    */
-  if (gtk_text_btree_mark_is_insert (layout->buffer->tree, seg) &&
+  if (gtk_text_btree_mark_is_insert (layout->buffer->tree, (GtkTextMark*)seg) &&
       gtk_text_buffer_get_selection_bounds (layout->buffer, &selection_start, &selection_end))
     return;
   
index 739504732b7f401dfa1be548d719e54f43f97753..72cb4f1bab9f16d9d33c17309d367d0652a07ece 100644 (file)
@@ -68,6 +68,7 @@ mark_segment_new(GtkTextBTree *tree,
   mark->body.mark.refcount = 1;
 
   mark->body.mark.visible = FALSE;
+  mark->body.mark.not_deleteable = FALSE;
   
   return mark;
 }
index 20ed1d5b085e8d378abd8db6aa6307f19d291b99..578e68036b64e6808d3546f0d6a6713617279dac 100644 (file)
@@ -7,6 +7,10 @@ extern "C" {
 
 #include <gtk/gtktexttypes.h>
 
+
+#define GTK_IS_TEXT_MARK(mark) (((GtkTextLineSegment*)mark)->type == &gtk_text_left_mark_type || \
+                                ((GtkTextLineSegment*)mark)->type == &gtk_text_right_mark_type)
+
 /*
  * The data structure below defines line segments that represent
  * marks.  There is one of these for each mark in the text.
@@ -17,12 +21,13 @@ struct _GtkTextMarkBody {
   gchar *name;
   GtkTextBTree *tree;
   GtkTextLine *line;
-  gboolean visible;
+  guint visible : 1;
+  guint not_deleteable : 1;
 };
 
 GtkTextLineSegment *mark_segment_new   (GtkTextBTree   *tree,
-                                     gboolean         left_gravity,
-                                     const gchar     *name);
+                                        gboolean         left_gravity,
+                                        const gchar     *name);
 void             mark_segment_ref   (GtkTextLineSegment *mark);
 void             mark_segment_unref (GtkTextLineSegment *mark);
 
index c76b46fcc3135c40a615b39214696043da7bab3b..a21d42bcc1ed7b4a1162e1ac741588ae1f1233dc 100644 (file)
@@ -52,10 +52,7 @@ struct _GtkTextTag {
    * defaults if no tag specifies an override.
    */
 
-  GtkTextStyleValues *values;
-  
-  /* tag contains appearance-related options */
-  guint affects_size : 1;
+  GtkTextStyleValues *values;  
   
   /*
     Flags for whether a given value is set; if a value is unset, then
index 31bc165b2a75ce7b422ecb540ba33b24cba20117..96318efc2c8f0c1cc483571820a18801234f01aa 100644 (file)
@@ -725,7 +725,7 @@ set_adjustment_clamped (GtkAdjustment *adj, gfloat val)
 
 gboolean
 gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view,
-                                      const gchar *mark_name,
+                                       GtkTextMark *mark,
                                       gint margin,
                                       gfloat percentage)
 {
@@ -741,7 +741,7 @@ gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view,
   gint current_x_scroll, current_y_scroll;
   
   g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
-  g_return_val_if_fail (mark_name != NULL, FALSE);
+  g_return_val_if_fail (mark != NULL, FALSE);
 
   widget = GTK_WIDGET (text_view);
   
@@ -750,12 +750,8 @@ gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view,
       g_warning ("FIXME need to implement scroll_to_mark for unmapped GtkTextView?");
       return FALSE;
     }
-  
-  if (!gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter, mark_name))
-    {
-      g_warning ("Mark %s does not exist! can't scroll to it.", mark_name);
-      return FALSE;
-    }
+
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter, mark);
   
   gtk_text_layout_get_iter_location (text_view->layout,
                                      &iter,
@@ -852,12 +848,12 @@ gtk_text_view_scroll_to_mark_adjusted (GtkTextView *text_view,
 
 gboolean
 gtk_text_view_scroll_to_mark (GtkTextView *text_view,
-                          const gchar *mark_name,
-                          gint mark_within_margin)
+                              GtkTextMark *mark,
+                              gint mark_within_margin)
 {
   g_return_val_if_fail (mark_within_margin >= 0, FALSE);
   
-  return gtk_text_view_scroll_to_mark_adjusted (text_view, mark_name,
+  return gtk_text_view_scroll_to_mark_adjusted (text_view, mark,
                                                mark_within_margin, 1.0);
 }
 
@@ -874,19 +870,18 @@ clamp_iter_onscreen (GtkTextView *text_view, GtkTextIter *iter)
 
 gboolean
 gtk_text_view_move_mark_onscreen (GtkTextView *text_view,
-                                 const gchar *mark_name)
+                                  GtkTextMark *mark)
 {
-  GtkTextIter mark;
+  GtkTextIter iter;
   
   g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
-  g_return_val_if_fail (mark_name != NULL, FALSE);
+  g_return_val_if_fail (mark != NULL, FALSE);
   
-  if (!gtk_text_buffer_get_iter_at_mark (text_view->buffer, &mark, mark_name))
-    return FALSE;
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &iter, mark);
   
-  if (clamp_iter_onscreen (text_view, &mark))
+  if (clamp_iter_onscreen (text_view, &iter))
     {
-      gtk_text_buffer_move_mark (text_view->buffer, mark_name, &mark);
+      gtk_text_buffer_move_mark (text_view->buffer, mark, &iter);
       return TRUE;
     }
   else
@@ -948,7 +943,9 @@ gtk_text_view_place_cursor_onscreen (GtkTextView *text_view)
   
   g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
   
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert, "insert");
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"));
   
   if (clamp_iter_onscreen (text_view, &insert))
     {
@@ -1148,9 +1145,8 @@ static void
 gtk_text_view_get_first_para_iter (GtkTextView *text_view,
                                   GtkTextIter *iter)
 {
-  gchar *mark_name = gtk_text_mark_get_name (text_view->first_para_mark);
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, iter, mark_name);
-  g_free (mark_name);
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, iter,
+                                    text_view->first_para_mark);
 }
 
 static void
@@ -1492,7 +1488,10 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
   else if (event->keyval == GDK_Return)
     {
       gtk_text_buffer_insert_at_cursor (text_view->buffer, "\n", 1);
-      gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+      gtk_text_view_scroll_to_mark (text_view,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"),
+                                    0);
       return TRUE;
     }
   else
@@ -1755,7 +1754,9 @@ gtk_text_view_move_insert (GtkTextView *text_view,
   
   gint cursor_x_pos = 0;
 
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert, "insert");
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"));
   newplace = insert;
 
   if (step == GTK_TEXT_MOVEMENT_LINE)
@@ -1810,11 +1811,16 @@ gtk_text_view_move_insert (GtkTextView *text_view,
   if (!gtk_text_iter_equal (&insert, &newplace))
     {
       if (extend_selection)
-       gtk_text_buffer_move_mark (text_view->buffer, "insert", &newplace);
+       gtk_text_buffer_move_mark (text_view->buffer,
+                                   gtk_text_buffer_get_mark (text_view->buffer,
+                                                             "insert"),
+                                   &newplace);
       else
        gtk_text_buffer_place_cursor (text_view->buffer, &newplace);
       
-      gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+      gtk_text_view_scroll_to_mark (text_view,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"), 0);
 
       if (step == GTK_TEXT_MOVEMENT_LINE)
        {
@@ -1828,7 +1834,9 @@ gtk_text_view_set_anchor (GtkTextView *text_view)
 {
   GtkTextIter insert;
   
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert, "insert");
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"));
 
   gtk_text_buffer_create_mark (text_view->buffer, "anchor", &insert, TRUE);
 }
@@ -1917,7 +1925,10 @@ gtk_text_view_scroll_text (GtkTextView *text_view,
   /* Adjust to have the cursor _entirely_ onscreen, move_mark_onscreen
    * only guarantees 1 pixel onscreen.
    */
-  gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+  gtk_text_view_scroll_to_mark (text_view,
+                                gtk_text_buffer_get_mark (text_view->buffer,
+                                                          "insert"),
+                                0);
 }
 
 static gboolean
@@ -1966,7 +1977,8 @@ gtk_text_view_delete_text (GtkTextView *text_view,
   
   gtk_text_buffer_get_iter_at_mark (text_view->buffer,
                                     &insert,
-                                    "insert");
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"));
 
   start = insert;
   end = insert;
@@ -2044,7 +2056,9 @@ gtk_text_view_delete_text (GtkTextView *text_view,
       if (leave_one)
         gtk_text_buffer_insert_at_cursor (text_view->buffer, " ", 1);
       
-      gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+      gtk_text_view_scroll_to_mark (text_view,
+                                    gtk_text_buffer_get_mark (text_view->buffer, "insert"),
+                                    0);
     }
 }
 
@@ -2052,21 +2066,30 @@ static void
 gtk_text_view_cut_text (GtkTextView *text_view)
 {
   gtk_text_buffer_cut (text_view->buffer, GDK_CURRENT_TIME);
-  gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+  gtk_text_view_scroll_to_mark (text_view,
+                                gtk_text_buffer_get_mark (text_view->buffer,
+                                                          "insert"),
+                                0);
 }
 
 static void
 gtk_text_view_copy_text (GtkTextView *text_view)
 {
   gtk_text_buffer_copy (text_view->buffer, GDK_CURRENT_TIME);
-  gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+  gtk_text_view_scroll_to_mark (text_view,
+                                gtk_text_buffer_get_mark (text_view->buffer,
+                                                          "insert"),
+                                0);
 }
 
 static void
 gtk_text_view_paste_text (GtkTextView *text_view)
 {
   gtk_text_buffer_paste_clipboard (text_view->buffer, GDK_CURRENT_TIME);
-  gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+  gtk_text_view_scroll_to_mark (text_view,
+                                gtk_text_buffer_get_mark (text_view->buffer,
+                                                          "insert"),
+                                0);
 }
 
 static void
@@ -2123,15 +2146,17 @@ move_insert_to_pointer_and_scroll (GtkTextView *text_view, gboolean partial_scro
   
   {
       gboolean scrolled = FALSE;
+      GtkTextMark *insert_mark =
+        gtk_text_buffer_get_mark (text_view->buffer, "insert");
 
       gtk_text_buffer_move_mark (text_view->buffer,
-                                 "insert",
+                                 insert_mark,
                                  &newplace);
       
       if (partial_scroll)
-        scrolled = gtk_text_view_scroll_to_mark_adjusted (text_view, "insert", 0, 0.7);
+        scrolled = gtk_text_view_scroll_to_mark_adjusted (text_view, insert_mark, 0, 0.7);
       else
-        scrolled = gtk_text_view_scroll_to_mark_adjusted (text_view, "insert", 0, 1.0);
+        scrolled = gtk_text_view_scroll_to_mark_adjusted (text_view, insert_mark, 0, 1.0);
 
       if (scrolled)
         {
@@ -2588,7 +2613,8 @@ gtk_text_view_drag_motion (GtkWidget        *widget,
     }
 
   gtk_text_buffer_move_mark (text_view->buffer,
-                             "__drag_target",
+                             gtk_text_buffer_get_mark (text_view->buffer,
+                                                       "__drag_target"),
                              &newplace);
 
   {
@@ -2600,7 +2626,10 @@ gtk_text_view_drag_motion (GtkWidget        *widget,
     margin = MIN (widget->allocation.width, widget->allocation.height);
     margin /= 5;
     
-    gtk_text_view_scroll_to_mark_adjusted (text_view, "__drag_target", margin, 1.0);
+    gtk_text_view_scroll_to_mark_adjusted (text_view,
+                                           gtk_text_buffer_get_mark (text_view->buffer,
+                                                                     "__drag_target"),
+                                           margin, 1.0);
   }
   
   return TRUE;
@@ -2639,6 +2668,8 @@ gtk_text_view_drag_data_received (GtkWidget        *widget,
 {
   GtkTextIter drop_point;
   GtkTextView *text_view;
+  GtkTextMark *drag_target_mark;
+  
   enum {INVALID, STRING, CTEXT, UTF8} type;
 
   text_view = GTK_TEXT_VIEW (widget);
@@ -2659,8 +2690,16 @@ gtk_text_view_drag_data_received (GtkWidget        *widget,
       return;
     }
 
-  if (!gtk_text_buffer_get_iter_at_mark (text_view->buffer, &drop_point, "__drag_target"))
+  drag_target_mark = gtk_text_buffer_get_mark (text_view->buffer,
+                                               "__drag_target");
+  
+  if (drag_target_mark == NULL)
     return;
+
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer,
+                                    &drop_point,
+                                    drag_target_mark);
+
   
   switch (type)
     {
@@ -2780,7 +2819,6 @@ gtk_text_view_value_changed (GtkAdjustment *adj,
                             GtkTextView   *text_view)
 {
   GtkTextIter iter;
-  gchar *mark_name;
   gint line_top;
   gint dx = 0;
   gint dy = 0;
@@ -2799,9 +2837,7 @@ gtk_text_view_value_changed (GtkAdjustment *adj,
        {
          gtk_text_layout_get_line_at_y (text_view->layout, &iter, adj->value, &line_top);
          
-         mark_name = gtk_text_mark_get_name (text_view->first_para_mark);
-         gtk_text_buffer_move_mark (text_view->buffer, mark_name, &iter);
-         g_free (mark_name);
+         gtk_text_buffer_move_mark (text_view->buffer, text_view->first_para_mark, &iter);
          
          text_view->first_para_pixels = adj->value - line_top;
        }
@@ -2832,7 +2868,10 @@ gtk_text_view_commit_handler (GtkIMContext  *context,
       gtk_text_buffer_insert_at_cursor (text_view->buffer, str, strlen (str));
     }
   
-  gtk_text_view_scroll_to_mark (text_view, "insert", 0);
+  gtk_text_view_scroll_to_mark (text_view,
+                                gtk_text_buffer_get_mark (text_view->buffer,
+                                                          "insert"),
+                                0);
 }
 
 static void
@@ -2858,7 +2897,9 @@ gtk_text_view_get_virtual_cursor_pos (GtkTextView *text_view,
   GdkRectangle strong_pos;
   GtkTextIter insert;
 
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert, "insert");
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"));
   
   if ((x && text_view->virtual_cursor_x == -1) ||
       (y && text_view->virtual_cursor_y == -1))
@@ -2889,7 +2930,9 @@ gtk_text_view_set_virtual_cursor_pos (GtkTextView *text_view,
   GdkRectangle strong_pos;
   GtkTextIter insert;
 
-  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert, "insert");
+  gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert,
+                                    gtk_text_buffer_get_mark (text_view->buffer,
+                                                              "insert"));
   
   if (x == -1 || y == -1)
     gtk_text_layout_get_cursor_locations (text_view->layout, &insert, &strong_pos, NULL);
index ba46ae6b470eaa9e7c002411da79e76a685ed3a0..002d3cd01fd71879f575e519f71c146342f8f02c 100644 (file)
@@ -132,10 +132,10 @@ void           gtk_text_view_get_iter_at_pixel     (GtkTextView   *text_view,
                                                    gint           x,
                                                    gint           y);
 gboolean       gtk_text_view_scroll_to_mark        (GtkTextView   *text_view,
-                                                   const gchar   *mark_name,
+                                                    GtkTextMark   *mark,
                                                    gint           mark_within_margin);
 gboolean       gtk_text_view_move_mark_onscreen    (GtkTextView   *text_view,
-                                                   const gchar   *mark_name);
+                                                    GtkTextMark   *mark);
 gboolean       gtk_text_view_place_cursor_onscreen (GtkTextView   *text_view);
 
 void           gtk_text_view_get_visible_rect      (GtkTextView   *text_view,
index 478a6dfb211717ef3a794cfeb767f0c65d9952ed..3393596cdfd4c6e795c12e0677ecddf4b0ac30e0 100644 (file)
@@ -502,6 +502,8 @@ fill_example_buffer (GtkTextBuffer *buffer)
   i = 0;
   while (i < 100)
     {
+      GtkTextMark * temp_mark;
+      
       gtk_text_buffer_get_iter_at_char(buffer, &iter, 0);
           
       gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
@@ -521,7 +523,8 @@ fill_example_buffer (GtkTextBuffer *buffer)
                                really know how to display it */
                             "German (Deutsch Süd) Grüß Gott Greek (Ελληνικά) Γειά σας Hebrew   שלום Japanese (日本語)\n", -1);
 
-      gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
+      temp_mark =
+        gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
 
 #if 1
       gtk_text_buffer_get_iter_at_line_char(buffer, &iter, 0, 6);
@@ -555,16 +558,16 @@ fill_example_buffer (GtkTextBuffer *buffer)
       gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
 #endif
 
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter, "tmp_mark");
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter, temp_mark);
       gtk_text_buffer_insert (buffer, &iter, "Centered text!\n", -1);
          
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, "tmp_mark");
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
       gtk_text_buffer_apply_tag (buffer, "centered", &iter2, &iter);
 
-      gtk_text_buffer_move_mark (buffer, "tmp_mark", &iter);
+      gtk_text_buffer_move_mark (buffer, temp_mark, &iter);
       gtk_text_buffer_insert (buffer, &iter, "Word wrapped, Right-to-left Quote\n", -1);
       gtk_text_buffer_insert (buffer, &iter, "وقد بدأ ثلاث من أكثر المؤسسات تقدما في شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت في السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي في بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« في بوليفيا.\n", -1);
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, "tmp_mark");
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
       gtk_text_buffer_apply_tag (buffer, "rtl_quote", &iter2, &iter);
          
       ++i;
diff --git a/gtk/testtextbuffer.c b/gtk/testtextbuffer.c
new file mode 100644 (file)
index 0000000..dfd95bf
--- /dev/null
@@ -0,0 +1,393 @@
+/* Simplistic test suite */
+
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include "gtktextbtree.h"
+
+static void fill_buffer(GtkTextBuffer *buffer);
+
+static void run_tests(GtkTextBuffer *buffer);
+
+int
+main(int argc, char** argv)
+{
+  GtkTextBuffer *buffer;
+  int n;
+  GtkTextUniChar ch;
+  GtkTextIter start, end;
+  
+  gtk_init(&argc, &argv);
+
+  /* Check UTF8 unknown char thing */
+  g_assert(gtk_text_view_num_utf_chars(gtk_text_unknown_char_utf8, 3) == 1);
+  gtk_text_utf_to_unichar(gtk_text_unknown_char_utf8, &ch);
+  g_assert(ch == gtk_text_unknown_char);
+  
+  /* First, we turn on btree debugging. */
+  gtk_debug_flags |= GTK_DEBUG_TEXT;
+
+  /* Create a buffer */
+  buffer = gtk_text_buffer_new(NULL);
+
+  /* Check that buffer starts with one empty line and zero chars */
+  
+  n = gtk_text_buffer_get_line_count(buffer);
+  if (n != 1)
+    g_error("%d lines, expected 1", n);
+  
+  n = gtk_text_buffer_get_char_count(buffer);
+  if (n != 1)
+    g_error("%d chars, expected 1", n);
+  
+  /* Run gruesome alien test suite on buffer */
+  run_tests(buffer);
+  
+  /* Put stuff in the buffer */
+
+  fill_buffer(buffer);
+
+  /* Subject stuff-bloated buffer to further torment */
+  run_tests(buffer);
+
+  /* Delete all stuff from the buffer */
+  gtk_text_buffer_get_bounds(buffer, &start, &end);
+  gtk_text_buffer_delete(buffer, &start, &end);
+
+  /* Check buffer for emptiness (note that a single
+     empty line always remains in the buffer) */
+  n = gtk_text_buffer_get_line_count(buffer);
+  if (n != 1)
+    g_error("%d lines, expected 1", n);
+  
+  n = gtk_text_buffer_get_char_count(buffer);
+  if (n != 1)
+    g_error("%d chars, expected 1", n);
+
+  run_tests(buffer);
+  
+  return 0;
+}
+
+static void
+run_tests(GtkTextBuffer *buffer)
+{
+  GtkTextIter iter;
+  GtkTextIter start;
+  GtkTextIter end;
+  GtkTextIter mark;
+  gint i, j;
+  gint num_chars;
+  GtkTextMark *bar_mark;
+  
+  gtk_text_buffer_get_bounds(buffer, &start, &end);
+  
+  /* Check that walking the tree via chars and via indexes produces
+   * the same number of indexable locations.
+   */
+  num_chars = gtk_text_buffer_get_char_count(buffer);
+  iter = start;
+  bar_mark = gtk_text_buffer_create_mark(buffer, "bar", &iter, FALSE);
+  i = 0;
+  while (i < num_chars)
+    {
+      GtkTextIter current;
+      GtkTextMark *foo_mark;
+      
+      gtk_text_buffer_get_iter_at_char(buffer, &current, i);
+
+      if (!gtk_text_iter_equal(&iter, &current))
+        {
+          g_error("get_char_index didn't return current iter");
+        }
+
+      j = gtk_text_iter_get_char_index(&iter);
+
+      if (i != j)
+        {
+          g_error("iter converted to %d not %d", j, i);
+        }
+
+      /* get/set mark */
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, bar_mark);
+
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not moved to the right place.");
+        }
+      
+      foo_mark = gtk_text_buffer_create_mark(buffer, "foo", &iter, FALSE);
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, foo_mark);
+      gtk_text_buffer_delete_mark(buffer, foo_mark);
+      
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not created in the right place.");
+        }
+      
+      if (!gtk_text_iter_forward_char(&iter))
+        g_error("iterators ran out before chars");      
+
+      gtk_text_buffer_move_mark(buffer, bar_mark, &iter);
+      
+      ++i;
+    }
+
+  if (!gtk_text_iter_equal(&iter, &end))
+    g_error("Iterating over all chars didn't end with the end iter");
+
+  /* Do the tree-walk backward 
+   */
+  num_chars = gtk_text_buffer_get_char_count(buffer);
+  gtk_text_buffer_get_iter_at_char(buffer, &iter, -1);
+
+  gtk_text_buffer_move_mark(buffer, bar_mark, &iter);
+  
+  i = num_chars;
+
+  if (!gtk_text_iter_equal(&iter, &end))
+    g_error("iter at char -1 is not equal to the end iterator");
+  
+  while (i >= 0)
+    {
+      GtkTextIter current;
+      GtkTextMark *foo_mark;
+      
+      gtk_text_buffer_get_iter_at_char(buffer, &current, i);
+
+      if (!gtk_text_iter_equal(&iter, &current))
+        {
+          g_error("get_char_index didn't return current iter while going backward");
+        }
+      j = gtk_text_iter_get_char_index(&iter);
+
+      if (i != j)
+        {
+          g_error("going backward, iter converted to %d not %d", j, i);
+        }
+
+      /* get/set mark */
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, bar_mark);
+
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not moved to the right place.");
+        }
+      
+      foo_mark = gtk_text_buffer_create_mark(buffer, "foo", &iter, FALSE);
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, foo_mark);
+      gtk_text_buffer_delete_mark(buffer, foo_mark);
+      
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not created in the right place.");
+        }
+      
+      if (i > 0)
+        {
+          if (!gtk_text_iter_backward_char(&iter))
+            g_error("iterators ran out before char indexes");
+
+          gtk_text_buffer_move_mark(buffer, bar_mark, &iter);
+        }
+      else
+        {
+          if (gtk_text_iter_backward_char(&iter))
+            g_error("went backward from 0?");
+        }
+      
+      --i;
+    }
+  
+  if (!gtk_text_iter_equal(&iter, &start))
+    g_error("Iterating backward over all chars didn't end with the start iter");
+
+  /*
+   * Check that get_line_count returns the same number of lines
+   * as walking the tree by line
+   */
+  i = 1; /* include current (first) line */
+  gtk_text_buffer_get_iter_at_line(buffer, &iter, 0);
+  while (gtk_text_iter_forward_line(&iter))
+    ++i;
+
+  /* Add 1 to the line count, because 'i' counts the end-iterator line */
+  if (i != gtk_text_buffer_get_line_count(buffer) + 1)
+    g_error("Counted %d lines, buffer has %d", i,
+            gtk_text_buffer_get_line_count(buffer) + 1);
+}
+
+
+static char  *book_closed_xpm[] = {
+"16 16 6 1",
+"       c None s None",
+".      c black",
+"X      c red",
+"o      c yellow",
+"O      c #808080",
+"#      c white",
+"                ",
+"       ..       ",
+"     ..XX.      ",
+"   ..XXXXX.     ",
+" ..XXXXXXXX.    ",
+".ooXXXXXXXXX.   ",
+"..ooXXXXXXXXX.  ",
+".X.ooXXXXXXXXX. ",
+".XX.ooXXXXXX..  ",
+" .XX.ooXXX..#O  ",
+"  .XX.oo..##OO. ",
+"   .XX..##OO..  ",
+"    .X.#OO..    ",
+"     ..O..      ",
+"      ..        ",
+"                "};
+
+static void
+fill_buffer(GtkTextBuffer *buffer)
+{
+  GtkTextTag *tag;
+  GdkColor color, color2;
+  GtkTextIter iter;
+  GtkTextIter iter2;
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+  int i;
+  
+  tag = gtk_text_buffer_create_tag(buffer, "fg_blue");
+
+  color.red = color.green = 0;
+  color.blue = 0xffff;
+  color2.red = 0xfff;
+  color2.blue = 0x0;
+  color2.green = 0;
+  gtk_object_set(GTK_OBJECT(tag),
+                 "foreground_gdk", &color,
+                 "background_gdk", &color2,
+                 "font", "-*-courier-bold-r-*-*-30-*-*-*-*-*-*-*",
+                 NULL);
+
+  tag = gtk_text_buffer_create_tag(buffer, "fg_red");
+
+  color.blue = color.green = 0;
+  color.red = 0xffff;
+  gtk_object_set(GTK_OBJECT(tag),
+                 "offset", -4,
+                 "foreground_gdk", &color,
+                 NULL);
+
+  tag = gtk_text_buffer_create_tag(buffer, "bg_green");
+
+  color.blue = color.red = 0;
+  color.green = 0xffff;
+  gtk_object_set(GTK_OBJECT(tag),
+                 "background_gdk", &color,
+                 "font", "-*-courier-bold-r-*-*-10-*-*-*-*-*-*-*",
+                 NULL);
+
+  pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+                                                  gtk_widget_get_default_colormap(),
+                                                  &mask,
+                                                  NULL, book_closed_xpm);
+  
+  g_assert(pixmap != NULL);
+  
+  i = 0;
+  while (i < 10)
+    {
+      gchar *str;
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 0);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 1);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+      
+      str = g_strdup_printf("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
+                            i);
+      
+      gtk_text_buffer_insert(buffer, &iter, str, -1);
+
+      g_free(str);
+      
+      gtk_text_buffer_insert(buffer, &iter,
+                              "(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line\n\n"
+                              /* This is UTF8 stuff, Emacs doesn't
+                                 really know how to display it */
+                              "Spanish (Español) ¡Hola! / French (Français) Bonjour, Salut / German (Deutsch Süd) Grüß Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash)  (ภาษาไทย)  สวัสดีครับ, สวัสดีค่ะ\n",
+                              -1);  
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+      
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 4);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 7);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 8);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_line_char(buffer, &iter, 0, 8);
+      iter2 = iter;
+      gtk_text_iter_forward_chars(&iter2, 10);
+
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);
+
+      gtk_text_iter_forward_chars(&iter, 7);
+      gtk_text_iter_forward_chars(&iter2, 10);
+      
+      gtk_text_buffer_apply_tag(buffer, "bg_green", &iter, &iter2);
+
+      gtk_text_iter_forward_chars(&iter, 12);
+      gtk_text_iter_forward_chars(&iter2, 10);
+      
+      gtk_text_buffer_apply_tag(buffer, "bg_green", &iter, &iter2);
+
+      gtk_text_iter_forward_chars(&iter, 10);
+      gtk_text_iter_forward_chars(&iter2, 15);
+      
+      gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);      
+
+      gtk_text_iter_forward_chars(&iter, 20);
+      gtk_text_iter_forward_chars(&iter2, 20);
+      
+      gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);      
+
+      gtk_text_iter_backward_chars(&iter, 25);
+      gtk_text_iter_forward_chars(&iter2, 5);
+      
+      gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);      
+
+      gtk_text_iter_forward_chars(&iter, 15);
+      gtk_text_iter_backward_chars(&iter2, 10);
+
+      gtk_text_buffer_remove_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_remove_tag(buffer, "fg_blue", &iter, &iter2);      
+      
+      ++i;
+    }
+
+  gdk_pixmap_unref(pixmap);
+  if (mask)
+    gdk_bitmap_unref(mask);
+}
+
+
index 478a6dfb211717ef3a794cfeb767f0c65d9952ed..3393596cdfd4c6e795c12e0677ecddf4b0ac30e0 100644 (file)
@@ -502,6 +502,8 @@ fill_example_buffer (GtkTextBuffer *buffer)
   i = 0;
   while (i < 100)
     {
+      GtkTextMark * temp_mark;
+      
       gtk_text_buffer_get_iter_at_char(buffer, &iter, 0);
           
       gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
@@ -521,7 +523,8 @@ fill_example_buffer (GtkTextBuffer *buffer)
                                really know how to display it */
                             "German (Deutsch Süd) Grüß Gott Greek (Ελληνικά) Γειά σας Hebrew   שלום Japanese (日本語)\n", -1);
 
-      gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
+      temp_mark =
+        gtk_text_buffer_create_mark (buffer, "tmp_mark", &iter, TRUE);
 
 #if 1
       gtk_text_buffer_get_iter_at_line_char(buffer, &iter, 0, 6);
@@ -555,16 +558,16 @@ fill_example_buffer (GtkTextBuffer *buffer)
       gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
 #endif
 
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter, "tmp_mark");
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter, temp_mark);
       gtk_text_buffer_insert (buffer, &iter, "Centered text!\n", -1);
          
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, "tmp_mark");
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
       gtk_text_buffer_apply_tag (buffer, "centered", &iter2, &iter);
 
-      gtk_text_buffer_move_mark (buffer, "tmp_mark", &iter);
+      gtk_text_buffer_move_mark (buffer, temp_mark, &iter);
       gtk_text_buffer_insert (buffer, &iter, "Word wrapped, Right-to-left Quote\n", -1);
       gtk_text_buffer_insert (buffer, &iter, "وقد بدأ ثلاث من أكثر المؤسسات تقدما في شبكة اكسيون برامجها كمنظمات لا تسعى للربح، ثم تحولت في السنوات الخمس الماضية إلى مؤسسات مالية منظمة، وباتت جزءا من النظام المالي في بلدانها، ولكنها تتخصص في خدمة قطاع المشروعات الصغيرة. وأحد أكثر هذه المؤسسات نجاحا هو »بانكوسول« في بوليفيا.\n", -1);
-      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, "tmp_mark");
+      gtk_text_buffer_get_iter_at_mark (buffer, &iter2, temp_mark);
       gtk_text_buffer_apply_tag (buffer, "rtl_quote", &iter2, &iter);
          
       ++i;
diff --git a/tests/testtextbuffer.c b/tests/testtextbuffer.c
new file mode 100644 (file)
index 0000000..dfd95bf
--- /dev/null
@@ -0,0 +1,393 @@
+/* Simplistic test suite */
+
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include "gtktextbtree.h"
+
+static void fill_buffer(GtkTextBuffer *buffer);
+
+static void run_tests(GtkTextBuffer *buffer);
+
+int
+main(int argc, char** argv)
+{
+  GtkTextBuffer *buffer;
+  int n;
+  GtkTextUniChar ch;
+  GtkTextIter start, end;
+  
+  gtk_init(&argc, &argv);
+
+  /* Check UTF8 unknown char thing */
+  g_assert(gtk_text_view_num_utf_chars(gtk_text_unknown_char_utf8, 3) == 1);
+  gtk_text_utf_to_unichar(gtk_text_unknown_char_utf8, &ch);
+  g_assert(ch == gtk_text_unknown_char);
+  
+  /* First, we turn on btree debugging. */
+  gtk_debug_flags |= GTK_DEBUG_TEXT;
+
+  /* Create a buffer */
+  buffer = gtk_text_buffer_new(NULL);
+
+  /* Check that buffer starts with one empty line and zero chars */
+  
+  n = gtk_text_buffer_get_line_count(buffer);
+  if (n != 1)
+    g_error("%d lines, expected 1", n);
+  
+  n = gtk_text_buffer_get_char_count(buffer);
+  if (n != 1)
+    g_error("%d chars, expected 1", n);
+  
+  /* Run gruesome alien test suite on buffer */
+  run_tests(buffer);
+  
+  /* Put stuff in the buffer */
+
+  fill_buffer(buffer);
+
+  /* Subject stuff-bloated buffer to further torment */
+  run_tests(buffer);
+
+  /* Delete all stuff from the buffer */
+  gtk_text_buffer_get_bounds(buffer, &start, &end);
+  gtk_text_buffer_delete(buffer, &start, &end);
+
+  /* Check buffer for emptiness (note that a single
+     empty line always remains in the buffer) */
+  n = gtk_text_buffer_get_line_count(buffer);
+  if (n != 1)
+    g_error("%d lines, expected 1", n);
+  
+  n = gtk_text_buffer_get_char_count(buffer);
+  if (n != 1)
+    g_error("%d chars, expected 1", n);
+
+  run_tests(buffer);
+  
+  return 0;
+}
+
+static void
+run_tests(GtkTextBuffer *buffer)
+{
+  GtkTextIter iter;
+  GtkTextIter start;
+  GtkTextIter end;
+  GtkTextIter mark;
+  gint i, j;
+  gint num_chars;
+  GtkTextMark *bar_mark;
+  
+  gtk_text_buffer_get_bounds(buffer, &start, &end);
+  
+  /* Check that walking the tree via chars and via indexes produces
+   * the same number of indexable locations.
+   */
+  num_chars = gtk_text_buffer_get_char_count(buffer);
+  iter = start;
+  bar_mark = gtk_text_buffer_create_mark(buffer, "bar", &iter, FALSE);
+  i = 0;
+  while (i < num_chars)
+    {
+      GtkTextIter current;
+      GtkTextMark *foo_mark;
+      
+      gtk_text_buffer_get_iter_at_char(buffer, &current, i);
+
+      if (!gtk_text_iter_equal(&iter, &current))
+        {
+          g_error("get_char_index didn't return current iter");
+        }
+
+      j = gtk_text_iter_get_char_index(&iter);
+
+      if (i != j)
+        {
+          g_error("iter converted to %d not %d", j, i);
+        }
+
+      /* get/set mark */
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, bar_mark);
+
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not moved to the right place.");
+        }
+      
+      foo_mark = gtk_text_buffer_create_mark(buffer, "foo", &iter, FALSE);
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, foo_mark);
+      gtk_text_buffer_delete_mark(buffer, foo_mark);
+      
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not created in the right place.");
+        }
+      
+      if (!gtk_text_iter_forward_char(&iter))
+        g_error("iterators ran out before chars");      
+
+      gtk_text_buffer_move_mark(buffer, bar_mark, &iter);
+      
+      ++i;
+    }
+
+  if (!gtk_text_iter_equal(&iter, &end))
+    g_error("Iterating over all chars didn't end with the end iter");
+
+  /* Do the tree-walk backward 
+   */
+  num_chars = gtk_text_buffer_get_char_count(buffer);
+  gtk_text_buffer_get_iter_at_char(buffer, &iter, -1);
+
+  gtk_text_buffer_move_mark(buffer, bar_mark, &iter);
+  
+  i = num_chars;
+
+  if (!gtk_text_iter_equal(&iter, &end))
+    g_error("iter at char -1 is not equal to the end iterator");
+  
+  while (i >= 0)
+    {
+      GtkTextIter current;
+      GtkTextMark *foo_mark;
+      
+      gtk_text_buffer_get_iter_at_char(buffer, &current, i);
+
+      if (!gtk_text_iter_equal(&iter, &current))
+        {
+          g_error("get_char_index didn't return current iter while going backward");
+        }
+      j = gtk_text_iter_get_char_index(&iter);
+
+      if (i != j)
+        {
+          g_error("going backward, iter converted to %d not %d", j, i);
+        }
+
+      /* get/set mark */
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, bar_mark);
+
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not moved to the right place.");
+        }
+      
+      foo_mark = gtk_text_buffer_create_mark(buffer, "foo", &iter, FALSE);
+      gtk_text_buffer_get_iter_at_mark(buffer, &mark, foo_mark);
+      gtk_text_buffer_delete_mark(buffer, foo_mark);
+      
+      if (!gtk_text_iter_equal(&iter, &mark))
+        {
+          gtk_text_iter_spew(&iter, "iter");
+          gtk_text_iter_spew(&mark, "mark");
+          g_error("Mark not created in the right place.");
+        }
+      
+      if (i > 0)
+        {
+          if (!gtk_text_iter_backward_char(&iter))
+            g_error("iterators ran out before char indexes");
+
+          gtk_text_buffer_move_mark(buffer, bar_mark, &iter);
+        }
+      else
+        {
+          if (gtk_text_iter_backward_char(&iter))
+            g_error("went backward from 0?");
+        }
+      
+      --i;
+    }
+  
+  if (!gtk_text_iter_equal(&iter, &start))
+    g_error("Iterating backward over all chars didn't end with the start iter");
+
+  /*
+   * Check that get_line_count returns the same number of lines
+   * as walking the tree by line
+   */
+  i = 1; /* include current (first) line */
+  gtk_text_buffer_get_iter_at_line(buffer, &iter, 0);
+  while (gtk_text_iter_forward_line(&iter))
+    ++i;
+
+  /* Add 1 to the line count, because 'i' counts the end-iterator line */
+  if (i != gtk_text_buffer_get_line_count(buffer) + 1)
+    g_error("Counted %d lines, buffer has %d", i,
+            gtk_text_buffer_get_line_count(buffer) + 1);
+}
+
+
+static char  *book_closed_xpm[] = {
+"16 16 6 1",
+"       c None s None",
+".      c black",
+"X      c red",
+"o      c yellow",
+"O      c #808080",
+"#      c white",
+"                ",
+"       ..       ",
+"     ..XX.      ",
+"   ..XXXXX.     ",
+" ..XXXXXXXX.    ",
+".ooXXXXXXXXX.   ",
+"..ooXXXXXXXXX.  ",
+".X.ooXXXXXXXXX. ",
+".XX.ooXXXXXX..  ",
+" .XX.ooXXX..#O  ",
+"  .XX.oo..##OO. ",
+"   .XX..##OO..  ",
+"    .X.#OO..    ",
+"     ..O..      ",
+"      ..        ",
+"                "};
+
+static void
+fill_buffer(GtkTextBuffer *buffer)
+{
+  GtkTextTag *tag;
+  GdkColor color, color2;
+  GtkTextIter iter;
+  GtkTextIter iter2;
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+  int i;
+  
+  tag = gtk_text_buffer_create_tag(buffer, "fg_blue");
+
+  color.red = color.green = 0;
+  color.blue = 0xffff;
+  color2.red = 0xfff;
+  color2.blue = 0x0;
+  color2.green = 0;
+  gtk_object_set(GTK_OBJECT(tag),
+                 "foreground_gdk", &color,
+                 "background_gdk", &color2,
+                 "font", "-*-courier-bold-r-*-*-30-*-*-*-*-*-*-*",
+                 NULL);
+
+  tag = gtk_text_buffer_create_tag(buffer, "fg_red");
+
+  color.blue = color.green = 0;
+  color.red = 0xffff;
+  gtk_object_set(GTK_OBJECT(tag),
+                 "offset", -4,
+                 "foreground_gdk", &color,
+                 NULL);
+
+  tag = gtk_text_buffer_create_tag(buffer, "bg_green");
+
+  color.blue = color.red = 0;
+  color.green = 0xffff;
+  gtk_object_set(GTK_OBJECT(tag),
+                 "background_gdk", &color,
+                 "font", "-*-courier-bold-r-*-*-10-*-*-*-*-*-*-*",
+                 NULL);
+
+  pixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL,
+                                                  gtk_widget_get_default_colormap(),
+                                                  &mask,
+                                                  NULL, book_closed_xpm);
+  
+  g_assert(pixmap != NULL);
+  
+  i = 0;
+  while (i < 10)
+    {
+      gchar *str;
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 0);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 1);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+      
+      str = g_strdup_printf("%d Hello World!\nwoo woo woo woo woo woo woo woo\n",
+                            i);
+      
+      gtk_text_buffer_insert(buffer, &iter, str, -1);
+
+      g_free(str);
+      
+      gtk_text_buffer_insert(buffer, &iter,
+                              "(Hello World!)\nfoo foo Hello this is some text we are using to text word wrap. It has punctuation! gee; blah - hmm, great.\nnew line\n\n"
+                              /* This is UTF8 stuff, Emacs doesn't
+                                 really know how to display it */
+                              "Spanish (Español) ¡Hola! / French (Français) Bonjour, Salut / German (Deutsch Süd) Grüß Gott (testing Latin-1 chars encoded in UTF8)\nThai (we can't display this, just making sure we don't crash)  (ภาษาไทย)  สวัสดีครับ, สวัสดีค่ะ\n",
+                              -1);  
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+      
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 4);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 7);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_char(buffer, &iter, 8);
+      
+      gtk_text_buffer_insert_pixmap (buffer, &iter, pixmap, mask);
+
+      gtk_text_buffer_get_iter_at_line_char(buffer, &iter, 0, 8);
+      iter2 = iter;
+      gtk_text_iter_forward_chars(&iter2, 10);
+
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);
+
+      gtk_text_iter_forward_chars(&iter, 7);
+      gtk_text_iter_forward_chars(&iter2, 10);
+      
+      gtk_text_buffer_apply_tag(buffer, "bg_green", &iter, &iter2);
+
+      gtk_text_iter_forward_chars(&iter, 12);
+      gtk_text_iter_forward_chars(&iter2, 10);
+      
+      gtk_text_buffer_apply_tag(buffer, "bg_green", &iter, &iter2);
+
+      gtk_text_iter_forward_chars(&iter, 10);
+      gtk_text_iter_forward_chars(&iter2, 15);
+      
+      gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);      
+
+      gtk_text_iter_forward_chars(&iter, 20);
+      gtk_text_iter_forward_chars(&iter2, 20);
+      
+      gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);      
+
+      gtk_text_iter_backward_chars(&iter, 25);
+      gtk_text_iter_forward_chars(&iter2, 5);
+      
+      gtk_text_buffer_apply_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_apply_tag(buffer, "fg_blue", &iter, &iter2);      
+
+      gtk_text_iter_forward_chars(&iter, 15);
+      gtk_text_iter_backward_chars(&iter2, 10);
+
+      gtk_text_buffer_remove_tag(buffer, "fg_red", &iter, &iter2);
+      gtk_text_buffer_remove_tag(buffer, "fg_blue", &iter, &iter2);      
+      
+      ++i;
+    }
+
+  gdk_pixmap_unref(pixmap);
+  if (mask)
+    gdk_bitmap_unref(mask);
+}
+
+